package com.ai.service.made.impl;


import cn.hutool.core.collection.CollectionUtil;
import com.ai.common.CommonResponse;
import com.ai.common.constant.FunctionTypeConstants;
import com.ai.entity.BasePage;
import com.ai.entity.cameraFunctions.functions.CameraFunctionsPO;
import com.ai.entity.function.FunctionBO;
import com.ai.entity.function.FunctionPO;
import com.ai.entity.function.FunctionPage;
import com.ai.entity.function.FunctionVO;

import com.ai.entity.made.camera.CameraPO;
import com.ai.mapper.made.FunctionMapper;
import com.ai.service.made.CameraFunctionsService;
import com.ai.service.made.FunctionService;
import com.ai.service.made.IAlgorithmServerRelationService;
import com.ai.util.SecurityUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Mr.Chen
 * @since 2020-06-18
 */
@Slf4j
@Service
public class FunctionServiceImpl extends ServiceImpl<FunctionMapper, FunctionPO> implements FunctionService {

    @Resource
    FunctionMapper functionMapper;

    @Resource
    private IAlgorithmServerRelationService iAlgorithmServerRelationService;

    @Resource
    private CameraFunctionsService cameraFunctionsService;


    @Resource
    private AlgorithmCameraServiceImpl algorithmCameraService;

    @Override
    public CommonResponse oneById(FunctionPO functionPO) {
        return null;
    }

    @Override
    public CommonResponse modifyInfo(FunctionPO functionPO) {
        return null;
    }

    @Override
    public CommonResponse insert(FunctionPO functionPO) {

        Date date = new Date();
        functionPO.setCreateTime(date);
        functionPO.setUpdateTime(date);
        functionPO.setUpdateUser(SecurityUtils.getLoginUserName());
        functionPO.setCreateUser(SecurityUtils.getLoginUserName());
        functionPO.setRemark(functionPO.getNickname());
        functionPO.setThreshold(-1);
        functionPO.setUrl("-1");
        functionPO.setNumNickname("-1");
        functionPO.setNum(-1);
        save(functionPO);

        return CommonResponse.ok();


    }

    @Override
    public CommonResponse delete(FunctionPO functionPO) {
        return null;
    }

    @Override
    public CommonResponse selectByPage(FunctionPage page) {
        QueryWrapper<FunctionPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByAsc("type");
        //光流功能，仅是用于取流摄像头roi配置
        queryWrapper.ne("type",3001);
        queryWrapper = page.getQuery(queryWrapper);
        IPage<FunctionPO> iPage = page(page, queryWrapper);
        IPage<FunctionVO> voIPage = iPage.convert(FunctionVO::convertPOToVO);
        return CommonResponse.ok(voIPage);
    }

    @Override
    public CommonResponse selectByCamera(FunctionBO functionBO) {
        if (functionBO.getCameraId() == null || functionBO.getCameraId() == 0) {
            return CommonResponse.error("摄像头ID不能为空");
        }
        String nickname = "%";
        if (!StringUtils.isEmpty(functionBO.getNickname())) {
            nickname = "%" + functionBO.getNickname() + "%";
        }

        List<FunctionVO> functionVOS = new ArrayList<>();

        //数据库已存的集合
        List<FunctionVO> checkedList = functionMapper.functionCheckedList(functionBO.getCameraId(), nickname);
        Map<Integer, FunctionVO> checkedMap = new HashMap();
        checkedList.forEach(vo -> {
            JSONArray spot = JSON.parseArray(vo.getSpot());
            Integer key = vo.getId();
            if (checkedMap.containsKey(key)) {
                checkedMap.get(key).getSpots().add(spot);
                checkedMap.get(key).addNum();
            } else {
                vo.setSpots(new JSONArray());
                vo.getSpots().add(spot);
                vo.setNum(1);
                checkedMap.put(key, vo);
            }
            vo.setSpot(null);
        });
        checkedList = checkedMap.values().stream().collect(Collectors.toList());
        functionVOS.addAll(checkedList);

        //数据库未存的集合
        List<FunctionVO> uncheckedList = functionMapper.functionUncheckedList(functionBO.getCameraId(), nickname);
        uncheckedList.forEach(vo -> {
            vo.setState(2);
            vo.setSpots(JSON.parseArray(vo.getSpot()));
            vo.setSpot(null);
        });
        functionVOS.addAll(uncheckedList);
        return CommonResponse.ok(functionVOS);
    }

    @Override
    public String getNameByCode(final String functionType) {
        return functionMapper.getNameByCode(functionType);
    }

    @Override
    public CommonResponse selectAll() {
        QueryWrapper<FunctionPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("type");
        return CommonResponse.ok(list(queryWrapper));
    }

    @Override
    public FunctionPO getFunByType(Integer functionType) {
        QueryWrapper<FunctionPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("type",functionType);
        FunctionPO functionPO = this.getOne(queryWrapper);
        return functionPO;
    }

    @Override
    public CommonResponse delAlarm(String functionId) {

        // TODO: 2024-08-26 删除之前需要先，移除所有的算法资源，并检测当前算法是否在某台服务器上正在运行 （检测运行状态，若正在运行，则不允许删除）
        boolean existRunning = iAlgorithmServerRelationService.existAlgorithmRunning(functionId);

        if (!existRunning){
            //删除部署记录，删除部署文件，删除方法记录

            //删除指定功能
            this.removeById(functionId);

            return CommonResponse.ok("删除成功");
        }else {

            throw new RuntimeException("存在服务器正在运行该算法，请关闭该算法后再次尝试");
        }


    }


    @Override
    public CommonResponse editAlarm(FunctionPO functionPO) {
        /**
         * 这段代码逻辑是
         *  1.先获取functionPO的功能type值，然后判断是否是睡岗和脱岗，如果是则判断roi区域识别时间是否为空。
         *  2.获取function对象dbFunction。
         *  3.如果functionPO的roi区域识别时间不为空，则更新到新对象dbFunction中，并且更新更改人和更改时间，最后保存到数据库中。
         *  4.根据功能值找到所有拥有该功能的摄像头，将摄像头列表重新存入redis中。
         */
        String functionType = String.valueOf(functionPO.getType());

        if (functionType.equals(FunctionTypeConstants.REGULAR_POST_OFF)) {
            //睡岗脱岗功能的roi区域识别时间不能为空
            if (null == functionPO.getRoiDetectionInterval()){
                throw  new RuntimeException("固定岗位脱岗识别功能roi区域识别时间不能为空，请填充后重新提交");
            }
        }

        if (functionType.equals(FunctionTypeConstants.FIXED_POST_SLEEPING_POST)){
            if (null == functionPO.getRoiDetectionInterval()){
                throw  new RuntimeException("固定岗位睡岗识别roi区域识别时间不能为空，请填充后重新提交");
            }
        }

        FunctionPO dbFunction = getFunByType(functionPO.getType());
        if (null != functionPO.getRoiDetectionInterval()){
            dbFunction.setRoiDetectionInterval(functionPO.getRoiDetectionInterval());
        }
        dbFunction.setUpdateUser(SecurityUtils.getLoginUserName());
        dbFunction.setUpdateTime(new Date());

        updateById(dbFunction);

        //准备更新参数缓存
        List<CameraPO> cameraPOList =  cameraFunctionsService.getCameraPoListByFunctionType(dbFunction.getId());
        if (CollectionUtil.isNotEmpty(cameraPOList)){
            //准备更新缓存
            log.info("===========================  准备更新对应的缓存信息  ===========================");
            algorithmCameraService.cacheAppointCameraList(cameraPOList);
        }

        return CommonResponse.ok("功能参数修改完成");
    }

    @Override
    public CommonResponse getFunctionList() {

        List<FunctionPO> functionPOList = this.list(new QueryWrapper<FunctionPO>().ne("type",3001));
        List<HashMap<String, Object>> res = functionPOList.stream()
                .sorted(Comparator.comparing(FunctionPO::getNickname))
                .map(functionPO -> {
            HashMap<String, Object> hashMap = new HashMap<>(16);
            hashMap.put("label", functionPO.getNickname());
            hashMap.put("value", functionPO.getType());
            return hashMap;
        }).collect(Collectors.toList());

        return CommonResponse.ok(res);
    }

    @Override
    public List<String> getRelationCameraId(String functionType) {

        FunctionPO funByType = this.getFunByType(Integer.valueOf(functionType));
        if (Objects.isNull(funByType)){
            return null;
        }

        List<CameraFunctionsPO> functionsPOS = cameraFunctionsService.list(new QueryWrapper<CameraFunctionsPO>().eq("function_id", funByType.getId()));
        if (CollectionUtil.isNotEmpty(functionsPOS)){
            List<String> cameraIdList = functionsPOS.stream()
                    .map(CameraFunctionsPO::getCameraId)
                    .distinct()
                    .map(String::valueOf)
                    .collect(Collectors.toList());
            return cameraIdList;
        }
        return null;
    }


}
